/*
 * 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
 * 开发板官网：www.lckfb.com
 * 技术支持常驻论坛，任何技术问题欢迎随时交流学习
 * 立创论坛：club.szlcsc.com
 * 关注bilibili账号：【立创开发板】，掌握我们的最新动态！
 * 不靠卖板赚钱，以培养中国工程师为己任
 * Change Logs:
 * Date           Author       Notes
 * 2023-11-02     LCKFB-yzh    first version
 */

#include "bsp_dht11.h"
#include "driver/gpio.h"
#include "freertos/portmacro.h"
#include "rom/ets_sys.h"
float temperature = 0;
float humidity = 0;

void Delay_ms(uint16 ms)
{
    vTaskDelay(ms / portTICK_PERIOD_MS);
}

// 温湿度定义
uchar ucharFLAG, uchartemp;
float Humi, Temp;
uchar ucharT_data_H, ucharT_data_L, ucharRH_data_H, ucharRH_data_L, ucharcheckdata;
uchar ucharT_data_H_temp, ucharT_data_L_temp, ucharRH_data_H_temp, ucharRH_data_L_temp, ucharcheckdata_temp;
uchar ucharcomdata;

uchar Humi_small;
uchar Temp_small;

static void InputInitial(void) // 设置端口为输入
{
    esp_rom_gpio_pad_select_gpio(GPIO_DHT11);
    gpio_set_direction(GPIO_DHT11, GPIO_MODE_INPUT);
}

static void OutputHigh(void) // 输出1
{
    esp_rom_gpio_pad_select_gpio(GPIO_DHT11);
    gpio_set_direction(GPIO_DHT11, GPIO_MODE_OUTPUT);
    gpio_set_level(GPIO_DHT11, 1);
}

static void OutputLow(void) // 输出0
{
    esp_rom_gpio_pad_select_gpio(GPIO_DHT11);
    gpio_set_direction(GPIO_DHT11, GPIO_MODE_OUTPUT);
    gpio_set_level(GPIO_DHT11, 0);
}

static uint8 getData() // 读取状态
{
    return gpio_get_level(GPIO_DHT11);
}

// 读取一个字节数据
static void COM(void)
{
    uchar i;
    for (i = 0; i < 8; i++)
    {
        ucharFLAG = 2;
        // 等待IO口变低，变低后，通过延时去判断是0还是1
        while ((getData() == 0) && ucharFLAG++)
            ets_delay_us(10);
        ets_delay_us(35); // 延时35us
        uchartemp = 0;

        // 如果这个位是1，35us后，还是1，否则为0
        if (getData() == 1)
            uchartemp = 1;
        ucharFLAG = 2;

        // 等待IO口变高，变高后，表示可以读取下一位
        while ((getData() == 1) && ucharFLAG++)
            ets_delay_us(10);
        if (ucharFLAG == 1)
            break;
        ucharcomdata <<= 1;
        ucharcomdata |= uchartemp;
    }
}

void DHT11(void) // 温湿传感启动
{
    OutputLow();
    Delay_ms(19); //>18MS
    OutputHigh();
    InputInitial(); // 输入
    ets_delay_us(30);
    if (!getData()) // 表示传感器拉低总线
    {
        ucharFLAG = 2;
        // 等待总线被传感器拉高
        while ((!getData()) && ucharFLAG++)
            ets_delay_us(10);
        // 等待总线被传感器拉低
        while ((getData()) && ucharFLAG++)
            ets_delay_us(10);
        COM(); // 读取第1字节，
        ucharRH_data_H_temp = ucharcomdata;
        COM(); // 读取第2字节，
        ucharRH_data_L_temp = ucharcomdata;
        COM(); // 读取第3字节，
        ucharT_data_H_temp = ucharcomdata;
        COM(); // 读取第4字节，
        ucharT_data_L_temp = ucharcomdata;
        COM(); // 读取第5字节，
        ucharcheckdata_temp = ucharcomdata;
        OutputHigh();
        // 判断校验和是否一致
        uchartemp = (ucharT_data_H_temp + ucharT_data_L_temp + ucharRH_data_H_temp + ucharRH_data_L_temp);
        if (uchartemp == ucharcheckdata_temp)
        {
            // 校验和一致，
            ucharRH_data_H = ucharRH_data_H_temp; // 湿度高8
            ucharRH_data_L = ucharRH_data_L_temp; // 湿度低8
            ucharT_data_H = ucharT_data_H_temp;   // 温度高8
            ucharT_data_L = ucharT_data_L_temp;   // 温度低8
            ucharcheckdata = ucharcheckdata_temp;

            // 保存温度和湿度
            Humi = ucharRH_data_H;
            Humi_small = ucharRH_data_L * 0.1;
            Humi = Humi + Humi_small;

            Temp = ucharT_data_H;
            Temp_small = ucharT_data_L * 0.1;
            Temp = Temp + Temp_small;
        }
        else
        {
            Humi = 100;
            Temp = 100;
        }
    }
    else // 没用成功读取，返回0
    {
        Humi = 0,
        Temp = 0;
    }

    OutputHigh(); // 输出
}
